//
//  RunLoopChapterViewController.m
//  ExerciseOC
//
//  Created by 王子曦 on 2025/4/14.
//

#import "RunLoopChapterViewController.h"

@interface RunLoopChapterViewController ()<UIScrollViewDelegate>
@property (nonatomic, strong) NSThread *persistentThread;
@property (nonatomic, assign) BOOL shouldKeepRunning;
@end

@implementation RunLoopChapterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    [self setupUI];
}

// 在 setupUI 方法中更新按钮数组和选择器数组
- (void)setupUI {
    // 添加说明标签
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, self.view.bounds.size.width - 40, 30)];
    titleLabel.text = @"RunLoop示例（请查看控制台输出）：";
    [self.view addSubview:titleLabel];
    
    // 创建按钮 - 修改buttonTitles数组
    NSArray *buttonTitles = @[@"RunLoop基本使用", 
                            @"RunLoop模式切换", 
                            @"CFRunLoopAddTimer函数原理", 
                            @"RunLoop观察者", 
                            @"RunLoop常驻线程",
                            @"子线程刷新不打断滑动",
                            @"滑动打断数据刷新",
                            @"CommonMode用法演示"];
    
    NSArray *selectors = @[[NSValue valueWithPointer:@selector(demonstrateBasicUsage)],
                          [NSValue valueWithPointer:@selector(demonstrateModeSwitching)],
                          [NSValue valueWithPointer:@selector(demonstrateCFRunLoopAddTimer)],
                          [NSValue valueWithPointer:@selector(demonstrateObserver)],
                          [NSValue valueWithPointer:@selector(demonstratePersistentThread)],
                          [NSValue valueWithPointer:@selector(demonstrateBackgroundRefresh)],
                          [NSValue valueWithPointer:@selector(demonstrateScrollInterruption)],
                          [NSValue valueWithPointer:@selector(demonstrateCommonModeUsage)]];
    
    for (NSInteger i = 0; i < buttonTitles.count; i++) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
        button.frame = CGRectMake(20, 140 + i * 50, self.view.bounds.size.width - 40, 40);
        [button setTitle:buttonTitles[i] forState:UIControlStateNormal];
        [button addTarget:self action:[selectors[i] pointerValue] forControlEvents:UIControlEventTouchUpInside];
        button.backgroundColor = [UIColor systemBlueColor];
        [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        button.layer.cornerRadius = 8;
        [self.view addSubview:button];
    }
}

#pragma mark - RunLoop示例方法

// RunLoop基本使用
- (void)demonstrateBasicUsage {
    NSLog(@"\n=== RunLoop基本使用 ===\n");
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"子线程开始: %@", [NSThread currentThread]);
        
        // 获取当前线程的RunLoop
        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        
        // 添加一个port源，防止RunLoop退出
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        
        // 运行RunLoop
        [runLoop run];
        
        // 这行代码不会执行，因为RunLoop一直在运行
        NSLog(@"RunLoop已退出");
    });
}

// RunLoop模式切换
- (void)demonstrateModeSwitching {
    NSLog(@"\n=== RunLoop模式切换 ===\n");
    
    // 添加UI元素
    UILabel *modeLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 340, self.view.bounds.size.width - 40, 30)];
    modeLabel.text = @"滑动下方视图观察模式切换";
    [self.view addSubview:modeLabel];
    
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 380, self.view.bounds.size.width - 40, 150)];
    scrollView.backgroundColor = [UIColor lightGrayColor];
    scrollView.contentSize = CGSizeMake(self.view.bounds.size.width - 40, 300);
    [self.view addSubview:scrollView];
    
    // 添加scrollView代理
    scrollView.delegate = self;
    
    __block CFRunLoopObserverRef observer = NULL;
    __block NSString *currentMode = @"DefaultMode";
    
    // 在主线程添加观察者
    dispatch_async(dispatch_get_main_queue(), ^{
        // 创建观察者
        observer = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
            // 获取当前RunLoop模式
            CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent());
            currentMode = (__bridge NSString *)mode;
            if (mode) CFRelease(mode);
            
            NSLog(@"RunLoop状态改变: %@, 当前模式: %@", [self runLoopActivityToString:activity], currentMode);
            
            // 更新UI
            modeLabel.text = [NSString stringWithFormat:@"当前模式: %@", currentMode];
        });
        
        // 添加观察者到主线程RunLoop的所有常见模式
        CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopCommonModes);
        
        // 创建两个定时器，分别添加到不同模式
        NSTimer *defaultTimer = [NSTimer timerWithTimeInterval:3.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"DefaultMode定时器触发");
        }];
        
        NSTimer *trackingTimer = [NSTimer timerWithTimeInterval:3.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"TrackingMode定时器触发");
        }];
        
        [[NSRunLoop currentRunLoop] addTimer:defaultTimer forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] addTimer:trackingTimer forMode:UITrackingRunLoopMode];
    });
}

// 添加UIScrollViewDelegate方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    // 这个方法会在滑动时被调用，确保RunLoop切换到Tracking模式
}

// RunLoop观察者
- (void)demonstrateObserver {
    NSLog(@"\n=== RunLoop观察者 ===\n");
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"子线程开始: %@", [NSThread currentThread]);
        
        // 创建观察者
        CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
            NSLog(@"RunLoop状态改变: %@", [self runLoopActivityToString:activity]);
        });
        
        // 添加观察者到当前RunLoop
        CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
        
        // 运行RunLoop
        [[NSRunLoop currentRunLoop] run];
        
        // 释放观察者
        CFRelease(observer);
    });
}

// RunLoop常驻线程
- (void)demonstratePersistentThread {
    NSLog(@"\n=== RunLoop常驻线程 ===\n");
    
    if (!self.persistentThread) {
        self.persistentThread = [[NSThread alloc] initWithTarget:self selector:@selector(runPersistentThread) object:nil];
        [self.persistentThread start];
    }
    
    // 向常驻线程提交任务
    [self performSelector:@selector(task1) onThread:self.persistentThread withObject:nil waitUntilDone:NO];
    [self performSelector:@selector(task2) onThread:self.persistentThread withObject:nil waitUntilDone:NO];
}

- (void)runPersistentThread {
    @autoreleasepool {
        NSLog(@"常驻线程启动: %@", [NSThread currentThread]);
        
        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        
        self.shouldKeepRunning = YES;
        while (self.shouldKeepRunning) {
            [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
        
        NSLog(@"常驻线程安全退出");
    }
}

// 辅助方法：转换RunLoop状态为字符串
- (NSString *)runLoopActivityToString:(CFRunLoopActivity)activity {
    switch (activity) {
        case kCFRunLoopEntry: return @"进入RunLoop";
        case kCFRunLoopBeforeTimers: return @"即将处理Timer";
        case kCFRunLoopBeforeSources: return @"即将处理Source";
        case kCFRunLoopBeforeWaiting: return @"即将进入休眠";
        case kCFRunLoopAfterWaiting: return @"从休眠中唤醒";
        case kCFRunLoopExit: return @"退出RunLoop";
        default: return @"未知状态";
    }
}

- (void)task1 {
    NSLog(@"执行任务1 (线程: %@)", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1];
}

- (void)task2 {
    NSLog(@"执行任务2 (线程: %@)", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1];
}

#pragma mark - 新增 CFRunLoopAddTimer 演示方法

// 演示 CFRunLoopAddTimer 函数原理
- (void)demonstrateCFRunLoopAddTimer {
    NSLog(@"\n=== CFRunLoopAddTimer 函数原理 ===\n");
    
    // 创建上下文
    CFRunLoopTimerContext timerContext = {
        0,                                      // 版本号
        (__bridge void *)self,                 // 信息指针
        NULL,                                  // retain函数
        NULL,                                  // release函数
        NULL                                   // copyDescription函数
    };
    
    // 创建CFRunLoopTimerRef
    CFRunLoopTimerRef timer = CFRunLoopTimerCreate(
        kCFAllocatorDefault,                   // 分配器
        CFAbsoluteTimeGetCurrent() + 2.0,      // 首次触发时间
        2.0,                                   // 间隔时间
        0,                                     // 标志位
        0,                                     // 优先级
        &CFRunLoopTimerCallback,               // 回调函数
        &timerContext                          // 上下文
    );
    
    // 将定时器添加到当前RunLoop的默认模式
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
    
    // 释放定时器(会被RunLoop retain)
    CFRelease(timer);
    
    NSLog(@"CFRunLoopTimer已创建并添加到RunLoop");
}

// CFRunLoopTimer回调函数
static void CFRunLoopTimerCallback(CFRunLoopTimerRef timer, void *info) {
    NSLog(@"CFRunLoopTimer触发，当前线程: %@", [NSThread currentThread]);
    
    // 可以通过info获取上下文信息
    RunLoopChapterViewController *self = (__bridge RunLoopChapterViewController *)info;
    [self performSelectorOnMainThread:@selector(updateTimerUI) withObject:nil waitUntilDone:NO];
}

// 更新UI的方法
- (void)updateTimerUI {
    NSLog(@"在主线程更新UI");
}

// 停止常驻线程
- (void)stopPersistentThread {
    if (self.persistentThread && self.persistentThread.isExecuting) {
        [self performSelector:@selector(setShouldKeepRunning:)
                   onThread:self.persistentThread
                 withObject:@(NO)
              waitUntilDone:NO];
        CFRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]);
        [self.persistentThread cancel];
    }
    self.persistentThread = nil;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self stopPersistentThread];
}

- (void)dealloc {
    [self stopPersistentThread];
    NSLog(@"ViewController已释放");
}

#pragma mark - 新增演示方法

// 演示子线程数据刷新不会打断滑动操作
- (void)demonstrateBackgroundRefresh {
    NSLog(@"\n=== 子线程刷新不打断滑动 ===\n");
    
    // 创建滚动视图
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 340, self.view.bounds.size.width - 40, 150)];
    scrollView.contentSize = CGSizeMake(self.view.bounds.size.width - 40, 300);
    scrollView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:scrollView];
    
    // 添加标签显示刷新状态
    UILabel *statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 500, self.view.bounds.size.width - 40, 30)];
    statusLabel.text = @"尝试滑动视图，观察数据刷新";
    [self.view addSubview:statusLabel];
    
    // 模拟后台数据刷新
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i = 0; i < 10; i++) {
            dispatch_async(dispatch_get_main_queue(), ^{
                statusLabel.text = [NSString stringWithFormat:@"数据刷新中...%d/10", i+1];
                NSLog(@"数据刷新 %d", i+1);
            });
            [NSThread sleepForTimeInterval:0.5];
        }
    });
}

// 演示滑动操作会打断数据刷新
- (void)demonstrateScrollInterruption {
    NSLog(@"\n=== 滑动打断数据刷新 ===\n");
    
    // 创建滚动视图
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 340, self.view.bounds.size.width - 40, 150)];
    scrollView.contentSize = CGSizeMake(self.view.bounds.size.width - 40, 300);
    scrollView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:scrollView];
    
    // 添加标签显示刷新状态
    UILabel *statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 500, self.view.bounds.size.width - 40, 30)];
    statusLabel.text = @"尝试快速滑动视图打断刷新";
    [self.view addSubview:statusLabel];
    
    // 模拟需要高优先级的UI刷新
    __block int counter = 0;
    [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        counter++;
        statusLabel.text = [NSString stringWithFormat:@"刷新计数: %d", counter];
        NSLog(@"定时刷新 %d", counter);
        
        if (counter >= 100) {
            [timer invalidate];
        }
    }];
}

#pragma mark - 新增 CommonMode 演示方法

// 演示 CommonMode 的用法
- (void)demonstrateCommonModeUsage {
    NSLog(@"\n=== CommonMode 用法演示 ===\n");
    
    // 创建说明标签
    UILabel *descLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 340, self.view.bounds.size.width - 40, 60)];
    descLabel.text = @"观察控制台输出：\n添加到CommonMode的Timer在任何模式下都会触发";
    descLabel.numberOfLines = 0;
    [self.view addSubview:descLabel];
    
    // 创建滚动视图用于触发模式切换
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 420, self.view.bounds.size.width - 40, 150)];
    scrollView.contentSize = CGSizeMake(self.view.bounds.size.width - 40, 300);
    scrollView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:scrollView];
    
    // 1. 创建并添加普通模式的Timer（只在Default模式触发）
    NSTimer *defaultTimer = [NSTimer timerWithTimeInterval:2.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"DefaultMode Timer触发 - 只在Default模式触发");
    }];
    [[NSRunLoop currentRunLoop] addTimer:defaultTimer forMode:NSDefaultRunLoopMode];
    
    // 2. 创建并添加CommonMode的Timer（会在所有CommonModes下触发）
    NSTimer *commonTimer = [NSTimer timerWithTimeInterval:2.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"CommonMode Timer触发 - 在Default和Tracking模式都会触发");
    }];
    [[NSRunLoop currentRunLoop] addTimer:commonTimer forMode:NSRunLoopCommonModes];
    
    // 3. 添加观察者查看当前模式
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        if (activity == kCFRunLoopBeforeTimers) {
            CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetCurrent());
            NSLog(@"当前RunLoop模式: %@", (__bridge NSString *)mode);
            if (mode) CFRelease(mode);
        }
    });
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopCommonModes);
}

@end
